package com.wsl.sharding.configuration;

import com.alibaba.druid.pool.DruidDataSource;
import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.wsl.sharding.pojo.DBDb;
import com.wsl.sharding.pojo.DbTable;
import com.wsl.sharding.share.DbShare;
import com.wsl.sharding.share.TableShare;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

//@Configuration
public class DataConifguration {


    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Bean
    public DataSource buildDataSource() throws SQLException {
        List<DbTable> tableList = (List<DbTable>) redisTemplate.opsForValue().get("db_table");

        List<DBDb> dbList = (List<DBDb>) redisTemplate.opsForValue().get("db_db");
        //1.设置分库映射
        Map<String,DataSource> dataSourceMap = new HashMap<>(dbList.size());
        for (DBDb dbTable : dbList) {
            dataSourceMap.put(dbTable.getDbName(),createDataSource(dbTable.getDbName()));
        }

        //设置默认db为ds_0,也就是为那些没有配置分库分表策略的指定默认库
        //如果只有一个库也就不需要分库的话。map里只放一个映射就行了。只有一个库时不需要指定默认的库
        //但2个及以上时必须指定默认库，否则那些没有配置策略的表将无法操作数据
        DataSourceRule rule = new DataSourceRule(dataSourceMap,dbList.get(0).getDbName());
        // 2.设置分表映射，将t_order_0 和t_order_1 两个实际的表映射到t_order逻辑表
        List<String> tableListShare = new ArrayList<>();
        for (DbTable dbTable :tableList) {
            tableListShare.add(dbTable.getTableName());
        }
        TableRule orderTableRule = TableRule.builder("person").actualTables(tableListShare).dataSourceRule(rule).build();
        //3.具体的分库分表策略
        ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(rule)
                .tableRules(Arrays.asList(orderTableRule))
                .databaseShardingStrategy(new DatabaseShardingStrategy("user_id",new DbShare()))  //分库使用
                .tableShardingStrategy(new TableShardingStrategy("order_id",new TableShare())).build(); //分表使用

        DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
        return dataSource;
    }

    private static DataSource createDataSource(String dataSourceName){
        //使用druid连接数据库
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        druidDataSource.setUrl(String.format("jdbc:mysql://localhost:3306/%s?serverTimezone=UTC&characterEncoding=utf-8",dataSourceName));
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("qwer1234");
        return druidDataSource;
    }
}
